﻿using System;
using System.Linq;
using System.Reflection;
using Autofac;
using Zinnia.Lite.Configs;
using Zinnia.Lite.Core;
using Zinnia.Lite.Core.Imp;
using Zinnia.Lite.Injection;

namespace Zinnia.Lite.Services.Imp
{
    /// <summary>
    /// 默认服务端口
    /// </summary>
    public sealed class ServiceHub : IServiceHub
    {
        /// <summary>
        /// 服务端口
        /// </summary>
        public static ServiceHub Instance => new ServiceHub();
        private ServiceHub()
        {
        }
        IContainerService _containerService;
        public IContainerService ContainerService => _containerService;
        LiteConfiguration LiteConfiguration => LiteConfigService.Instance.LiteConfiguration;
        public void Initialize()
        {
            var builder = new ContainerBuilder();
            var container = builder.Build();
            var typeFinder = new AppDomainTypeService();
            builder = new ContainerBuilder();
            builder.RegisterInstance(LiteConfiguration).As<LiteConfiguration>().SingleInstance();
            builder.RegisterInstance(Instance).As<IServiceHub>().SingleInstance();
            builder.RegisterInstance(typeFinder).As<ITypeService>().SingleInstance();
            builder.Update(container);
            builder = new ContainerBuilder();
            var assemblies = typeFinder.GetAssemblies();
            //人工注册器优先注入
            var drTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>();
            var drInstances = drTypes.Select(drType => (IDependencyRegistrar)Activator.CreateInstance(drType)).ToList();
            //sort
            drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
            foreach (var dependencyRegistrar in drInstances)
                dependencyRegistrar.Register(builder, typeFinder);
            //默认注入引擎
            builder.RegisterAssemblyTypes(assemblies.ToArray())
                .Where(t => typeof(ISingleDependency).IsAssignableFrom(t) && typeof(ISingleDependency) != t)
                .AsImplementedInterfaces()
                .SingleInstance();
            builder.RegisterAssemblyTypes(assemblies.ToArray()).Where(t => typeof(ITransientDependency).IsAssignableFrom(t) && typeof(ITransientDependency) != t).AsImplementedInterfaces()
                .InstancePerDependency();
            builder.RegisterAssemblyTypes(assemblies.ToArray()).Where(t => typeof(IUnitOfWorkDependency).IsAssignableFrom(t) && typeof(IUnitOfWorkDependency) != t).AsImplementedInterfaces()
                .InstancePerLifetimeScope();
            //注册http缓存，并标识成非默认
            builder.RegisterType<LocalCacheService>().As<ICacheService>().Named<ICacheService>("LocalCacheService").InstancePerLifetimeScope().PreserveExistingDefaults();
            this._containerService = (IContainerService)Activator.CreateInstance(Assembly.Load(LiteConfiguration.ContainerServiceTypeAssembly).GetType(LiteConfiguration.ContainerServiceType, false, true), container);
        }

        #region IServiceHub实现
        public object Resolve(Type type)
        {
            return ContainerService.Resolve(type);
        }

        public T Resolve<T>(string key = "", ILifetimeScope lifetimeScope = null) where T : class
        {
            return ContainerService.Resolve<T>(key, lifetimeScope);
        }

        public T[] ResolveAll<T>()
        {
            return ContainerService.ResolveAll<T>();
        }
        #endregion
    }
}
